package me.flyray.bsin.server.biz;

import com.plexpt.chatgpt.entity.billing.Usage;
import com.plexpt.chatgpt.entity.chat.ChatCompletionResponse;
import lombok.AllArgsConstructor;
import me.flyray.bsin.wordFilter.SensitiveWordFilter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.flyray.bsin.cache.BsinCacheProvider;
import me.flyray.bsin.server.config.ChatGPTConfiguration;
import me.flyray.bsin.server.domain.AiModel;
import me.flyray.bsin.server.domain.TenantWxPlatform;
import me.flyray.bsin.server.domain.TenantWxPlatformRole;
import me.flyray.bsin.server.domain.TenantWxPlatformUser;
import me.flyray.bsin.server.domain.TenantWxPlatformUserTag;
import me.flyray.bsin.server.mapper.AiModelMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformRoleMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformUserMapper;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformUserTagMapper;
import me.flyray.bsin.server.push.CustomerService;
import me.flyray.bsin.server.push.PushTemplateUtil;
import me.flyray.bsin.server.utils.OpenAI;
import me.flyray.bsin.thirdauth.wx.builder.TextBuilder;
import me.flyray.bsin.thirdauth.wx.handler.AbstractHandler;
import me.flyray.bsin.thirdauth.wx.utils.BsinWxMpServiceUtil;
import me.flyray.bsin.thirdauth.wx.utils.WxMpProperties;
import me.flyray.bsin.utils.BsinSnowflake;

/**
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@Component
public class MsgHandlerBiz extends AbstractHandler {

    public static final Map<String, Integer> dataMap = new HashMap<>();
    @Autowired
    private OpenAI openAI;
    @Autowired
    private AiModelMapper aiModelMapper;
    @Autowired
    private AiTenantWxPlatformMapper tenantWxmpMapper;
    @Autowired
    private AiTenantWxPlatformRoleMapper tenantWxmpRoleMapper;
    @Autowired
    private AiTenantWxPlatformUserMapper tenantWxmpUserMapper;
    @Autowired
    private AiTenantWxPlatformUserTagMapper tenantWxmpUserTagMapper;
    private static long last_time = 0;
    private static long current_time = 0;
    private final Environment environment;
    @Autowired
    BsinWxMpServiceUtil bsinWxMpServiceUtil;
    @Autowired
    private BsinCacheProvider bsinCacheProvider;
    @Value("${bsin.ai.aesKey}")
    private String aesKey;
    @Value("${bsin.ai.sensitiveWordPath}")
    private String sensitiveWordPath;
    @Autowired
    private SensitiveWordFilter sensitiveWordFilter;


//    private TenantWxmpUser tenantWxmpUser;

    public MsgHandlerBiz(Environment environment) {
        this.environment = environment;
    }

    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                    Map<String, Object> context, WxMpService wxMpService,
                                    WxSessionManager sessionManager) {

        //TODO 根据用户找到对应的appId，在找到公众号的配置，找到租户 找到对应的chatGPT
        // 根据用户的openid从缓存里面获取对应的appId
        String appId = bsinCacheProvider.get(wxMessage.getFromUser());
        String openId = wxMessage.getFromUser();
        TenantWxPlatform tenantWxPlatform = tenantWxmpMapper.selectByAppId(appId);
        WxMpProperties.MpConfig config = new WxMpProperties.MpConfig();
        config.setAesKey(tenantWxPlatform.getAesKey());
        config.setAppId(appId);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes());
        String wxAppSecret = aes.decryptStr(tenantWxPlatform.getAppSecret(), CharsetUtil.CHARSET_UTF_8);
        config.setSecret(wxAppSecret);
        config.setToken(tenantWxPlatform.getToken());

        // 判断用户是否存在
        TenantWxPlatformUser tenantWxPlatformUser = tenantWxmpUserMapper.selectByOpenId(openId);
        if (tenantWxPlatformUser == null) {
            tenantWxPlatformUser = new TenantWxPlatformUser();
            tenantWxPlatformUser.setTenantId(tenantWxPlatform.getTenantId());
            tenantWxPlatformUser.setOpenId(openId);
            tenantWxPlatformUser.setAppId(appId);
            tenantWxPlatformUser.setSerialNo(BsinSnowflake.getId());
            tenantWxPlatformUser.setCreateTime(new Date());
            tenantWxPlatformUser.setTokenBalance(100000);
            tenantWxPlatformUser.setTokenUsed(0);
            tenantWxmpUserMapper.insert(tenantWxPlatformUser);
        }

        TenantWxPlatformUserTag tenantWxmpUserTag = new TenantWxPlatformUserTag();
        tenantWxmpUserTag.setSerialNo(BsinSnowflake.getId());
        tenantWxmpUserTag.setTenantId(tenantWxPlatform.getTenantId());
        tenantWxmpUserTag.setTag(wxMessage.getContent());
        tenantWxmpUserTag.setOpenId(openId);
        tenantWxmpUserTag.setAppId(appId);
        tenantWxmpUserTagMapper.insert(tenantWxmpUserTag);

        WxMpService weixinService = bsinWxMpServiceUtil.getWxMpService(config,null);

        // 获取公众号配置的对应AI模型
        AiModel aiModel = aiModelMapper.selectBySerialNo(tenantWxPlatform.getAiModelNo());
        ChatGPTConfiguration chatGPTConfiguration = BeanUtil.copyProperties(aiModel, ChatGPTConfiguration.class);
        String openaiKey = aes.decryptStr(aiModel.getKey(), CharsetUtil.CHARSET_UTF_8);
        chatGPTConfiguration.setKey(openaiKey);
        List<String> openaiKeyList = Arrays.asList(openaiKey);
        chatGPTConfiguration.setKeyList(openaiKeyList);

        //AI模型的system role
        TenantWxPlatformRole tenantWxmpRole = tenantWxmpRoleMapper.selectByTenantId(tenantWxPlatform.getTenantId());
        chatGPTConfiguration.setSystemContent(tenantWxmpRole.getContent());

        if (!bsinCacheProvider.exist(appId + "TokenBalance")) {
            bsinCacheProvider.set(appId + "TokenBalance", tenantWxPlatformUser.getTokenBalance().toString());
        }
        if (!bsinCacheProvider.exist(appId + "TokenUsed")) {
            bsinCacheProvider.set(appId + "TokenUsed", tenantWxPlatformUser.getTokenUsed().toString());

        }
        long userTokenBalance = Long.parseLong(bsinCacheProvider.get(appId + "TokenBalance"));
        long userTokenUsed = Long.parseLong(bsinCacheProvider.get(appId + "TokenUsed"));

        // 非超时请求才做回复：limit时间
        current_time = System.currentTimeMillis();
        String preResponse = chatGPTConfiguration.getPreResponse();


        //敏感词过滤
        if (sensitiveWordFilter.wordList == null) {
            sensitiveWordFilter.loadWordFromFile(sensitiveWordPath);
        }
        Map<String, Object> ret = sensitiveWordFilter.Filter(wxMessage.getContent());
        if ((boolean) ret.get("isContain")) {
            return new TextBuilder().build("请求中涉及敏感词汇，拒绝答复！！！", wxMessage, weixinService);
        } else if (current_time - last_time > 5000) {
            //超时5s,进行异步发送消息
            Thread insertDbThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    String token = null;
                    try {
//                        String token = TokenManager.getAccessToken();
                        token = weixinService.getAccessToken();
                        System.out.println("token: " + token);
                        String responseContent = null;
                        ChatCompletionResponse chatCompletionResponse = null;
                        if (!chatGPTConfiguration.isRechargeable()) {
                            responseContent = openAI.chat(wxMessage, chatGPTConfiguration, tenantWxmpRole).getContent();
                        } else {
                            //计算token
                            if (userTokenBalance > chatGPTConfiguration.getMaxToken().longValue()) {
                                chatCompletionResponse = openAI.weChatCompletionResponse(wxMessage, chatGPTConfiguration, tenantWxmpRole);
                                responseContent = chatCompletionResponse.getChoices().get(0).getMessage().getContent();
                                Usage usage = chatCompletionResponse.getUsage();
                                System.out.println("usage: " + usage.toString());
                                bsinCacheProvider.set(appId + "TokenBalance", String.valueOf(userTokenBalance - usage.getTotalTokens()));
                                bsinCacheProvider.set(appId + "TokenUsed", String.valueOf(userTokenUsed + usage.getTotalTokens()));
                            } else {
                                System.out.println(appId + " 余额为：" + String.valueOf(userTokenBalance));
                                responseContent = chatGPTConfiguration.getOutofcreditResponse();
                                TenantWxPlatformUser tenantWxPlatformUser = tenantWxmpUserMapper.selectByOpenId(openId);
                                bsinCacheProvider.set(appId + "TokenBalance", tenantWxPlatformUser.getTokenBalance().toString());
                            }
                        }
                        CustomerService.connectWeiXinInterface(token, wxMessage.getFromUser(), responseContent);
                        if (chatGPTConfiguration.isTemplateEnable()) {
                            PushTemplateUtil.sendMessage(wxMessage.getFromUser(), wxMessage.getContent(), responseContent, weixinService);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        if (!StringUtils.isEmpty(token)) {
                            CustomerService.connectWeiXinInterface(token, wxMessage.getFromUser(), chatGPTConfiguration.getExceptionResponse());
                        }
                    }
                }
            });
            insertDbThread.start();
            last_time = current_time;
        } else {
            System.out.println("**************调用过于频繁或者是触发微信公众号retry机制****************");
            preResponse = chatGPTConfiguration.getExceptionResponse();
        }
        if (StringUtils.isEmpty(preResponse)) {
            return null;
        } else {
            return new TextBuilder().build(preResponse, wxMessage, weixinService);
        }
//        if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
//            //TODO 可以选择将消息保存到本地
//        }
//        //当用户输入关键词如“你好”，“客服”等，并且有客服在线时，把消息转发给在线客服
//        try {
//            if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服")
//                && weixinService.getKefuService().kfOnlineList()
//                .getKfOnlineList().size() > 0) {
//                return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE()
//                    .fromUser(wxMessage.getToUser())
//                    .toUser(wxMessage.getFromUser()).build();
//            }
//        } catch (WxErrorException e) {
//            e.printStackTrace();
//        }
    }
}
